#include "Dri_TIM4.h"

/**
 * @brief TIM4初始化
 * 
 */
void Dri_TIM4_Init(void)
{
    // 1. 时钟使能 --------------------------------------
    // 1.1 对 TIM4 时钟使能
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
    // 1.2 对 GPIOB 时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    // 2. GPIO 模式设置 ---------------------------------
    // 将 TIM4_CH1 (PB6) 设置为浮空输入(MODE=00, CNF=01, 默认值)或者复用推挽输出
    GPIOB->CRL &= ~GPIO_CRL_MODE6;
    GPIOB->CRL &= ~GPIO_CRL_CNF6_1;
    GPIOB->CRL |= GPIO_CRL_CNF6_0;

    // 3. TIM4 时基单元设置 -----------------------------
    // 3.1 设置计数器模式向上计数(默认值)
    TIM4->CR1 &= ~TIM_CR1_CMS;      // CMS=00, 关闭中央对齐模式
    TIM4->CR1 &= ~TIM_CR1_DIR;      // DIR=0, 向上计数
    // 3.2 设置预分配器的值，实现每1us计1个数, 可测量1MHz以下的PWM
    TIM4->PSC = 71;                 
    // 3.3 设置ARR自动重装载值，设置为最大置，可测量16Hz以上的PWM
    TIM4->ARR = 0xFFFF;

    // 3. TIM4 输入捕获设置 -----------------------------
    // 3.1 设置 TI1 选择 CH1 所对应的引脚 (CR2.TI1S=0, 默认值)
    TIM4->CR2 &= ~TIM_CR2_TI1S;      
    // 3.2 IC1、IC2 都不进行滤波 （CCMR1.IC1F=0000，CCMR1.IC2F=0000, 默认值）
    TIM4->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F);
    // 3.3 IC1捕获上升沿，IC2捕获下降沿 (CCER.CC1P=0, CCER.CC2P=1)
    TIM4->CCER &= ~TIM_CCER_CC1P;
    TIM4->CCER |= TIM_CCER_CC2P;
    // 3.4 设置IC1选择TI1FP1 (CCMR1.CC1S=01)，IC2选择TI1FP2 (CCMR1.CC2S=10)
    TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;   // CC1S=01
    TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;
    TIM4->CCMR1 |= TIM_CCMR1_CC2S_1;    // CC2S=10
    TIM4->CCMR1 &= ~TIM_CCMR1_CC2S_0;
    // 3.5 IC1、IC2 都不进行预分频 (CCMR1.IC1PSC=00, CCMR1.IC2PSC=00 默认值)
    TIM4->CCMR1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC);
    // 3.6 使能IC1、IC2 的输入捕获 (CCER.CC1E=1, CCER.CC2E=1)
    TIM4->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC2E);

    // 4. TIM4 从模式设置 -------------------------------
    // 4.1 设置TRGI 触发输入信号来源为TI1FP1 (SMCR.TS=101)
    TIM4->SMCR |= TIM_SMCR_TS_2;
    TIM4->SMCR &= ~TIM_SMCR_TS_1;
    TIM4->SMCR |= TIM_SMCR_TS_0;
    // 4.2 设置从模式为复位模式 (SMCR.SMS=100)
    TIM4->SMCR |= TIM_SMCR_SMS_2;
    TIM4->SMCR &= ~TIM_SMCR_SMS_1;
    TIM4->SMCR &= ~TIM_SMCR_SMS_0;
}

/**
 * @brief TIM4启动
 * 
 */
void Dri_TIM4_Start(void)
{
    // 使能计数
    TIM4->CR1 |= TIM_CR1_CEN;
}

/**
 * @brief TIM4停止
 *
 */
void Dri_TIM4_Stop(void)
{
    // 关闭使能计数
    TIM4->CR1 &= ~TIM_CR1_CEN;
}

/**
 * @brief 返回所测到的PWM周期时间
 * 
 * @return float 单位是 ms
 */
float Dri_TIM4_GetPWMPeriod(void)
{
    return TIM4->CCR1 / 1000.0;
}

/**
 * @brief 返回所测得的PWM频率
 * 
 * @return float 单位是Hz
 */
float Dri_TIM4_GetPWMFreq(void)
{
    return 1000 / Dri_TIM4_GetPWMPeriod();
}

/**
 * @brief 返回所测得的PWM占空比
 *
 * @return float 占空比,范围是0~1 (0%~100%)
 */
float Dri_TIM4_GetPWMDuty(void)
{
    return (float)TIM4->CCR2 / TIM4->CCR1;
}
